#include <QtGui/QMenu>
#include <QtGui/QToolBar>
#include <QtGui/QAction>
#include <QtGui/QComboBox>
#include <QtGui/QLabel>
#include <QtCore/QSettings>
#include "SessionsManager.h"
#include "AboutEditorDialog.h"
#include "InformationDialog.h"
#include "Const.h"
#include "Interface.h"

Interface::Interface(QWidget *parent) : AdvancedEditor(parent) {
	fileMenu = new QMenu("&" + tr("File"));
	editionMenu = new QMenu("&" + tr("Edit"));
	toolsMenu = new QMenu("&" + tr("Tools"));
	contextMenu = new QMenu;
	
	sessionsManager = new SessionsManager(this,parent);
	aboutEditorDialog = new AboutEditorDialog(parent);
	informationDialog = new InformationDialog(parent);
	
	toolBar = new QToolBar(tr("Show toolbar"));
	toolBar->setObjectName("MainToolBar");

	QAction *newAction = new QAction(parent);
	newAction->setText(tr("New tab"));
	newAction->setShortcut(QKeySequence::New);
	newAction->setIcon(QIcon(":/icons/tab-new.png"));
	connect(newAction,SIGNAL(triggered()),this,SLOT(newFile()));
	
	QAction *closeAction = new QAction(parent);
	closeAction->setText(tr("Close tab"));
	closeAction->setShortcut(QKeySequence::Close);
	closeAction->setIcon(QIcon(":/icons/tab-close.png"));
	connect(closeAction,SIGNAL(triggered()),this,SLOT(closeCurrentFile()));
	
	QAction *openAction = new QAction(parent);
	openAction->setText(tr("Open document"));
	openAction->setShortcut(QKeySequence::Open);
	openAction->setIcon(QIcon(":/icons/open.png"));
	connect(openAction,SIGNAL(triggered()),this,SLOT(openFiles()));
	
	QAction *saveAction = new QAction(parent);
	saveAction->setText(tr("Save document"));
	saveAction->setShortcut(QKeySequence::Save);
	saveAction->setIcon(QIcon(":/icons/save.png"));
	connect(saveAction,SIGNAL(triggered()),this,SLOT(saveCurrentFile()));
	
	QAction *saveAsAction = new QAction(parent);
	saveAsAction->setText(tr("Save document as"));
	saveAsAction->setShortcut(QKeySequence("Ctrl+Shift+S"));
	saveAsAction->setIcon(QIcon(":/icons/saveas.png"));
	connect(saveAsAction,SIGNAL(triggered()),this,SLOT(saveCurrentFileAs()));
	
	QAction *reloadAction = new QAction(parent);
	reloadAction->setText(tr("Reload document"));
	reloadAction->setShortcut(QKeySequence::Refresh);
	reloadAction->setIcon(QIcon(":/icons/reload.png"));
	connect(reloadAction,SIGNAL(triggered()),this,SLOT(reloadFile()));
	
	QAction *printAction = new QAction(parent);
	printAction->setText(tr("Print document"));
	printAction->setShortcut(QKeySequence::Print);
	printAction->setIcon(QIcon(":/icons/print.png"));
	connect(printAction,SIGNAL(triggered()),this,SLOT(printFile()));
	
	QAction *quitAction = new QAction(parent);
	quitAction->setText(tr("Quit"));
	quitAction->setShortcut(QKeySequence("Ctrl+Q"));
	quitAction->setIcon(QIcon(":/icons/quit.png"));
	connect(quitAction,SIGNAL(triggered()),this,SIGNAL(quit()));
	
	fileMenu->addAction(newAction);
	fileMenu->addAction(closeAction);
	fileMenu->addSeparator();
	fileMenu->addAction(openAction);
	fileMenu->addAction(saveAction);
	fileMenu->addAction(saveAsAction);
	fileMenu->addSeparator();
	fileMenu->addAction(reloadAction);
	fileMenu->addAction(printAction);
	fileMenu->addSeparator();
	fileMenu->addAction(quitAction);
	
	parent->addAction(newAction);
	parent->addAction(closeAction);
	parent->addAction(openAction);
	parent->addAction(saveAction);
	parent->addAction(saveAsAction);
	parent->addAction(reloadAction);
	parent->addAction(printAction);
	parent->addAction(quitAction);
	
	toolBar->addAction(newAction);
	toolBar->addAction(closeAction);
	toolBar->addAction(openAction);
	toolBar->addAction(saveAction);
	toolBar->addAction(saveAsAction);
	toolBar->addSeparator();
	
	filesManagementActions << newAction << closeAction << openAction << saveAction 
							<< saveAsAction << reloadAction << printAction << quitAction;
	
	QAction *undoAction = new QAction(editionMenu);
	undoAction->setText(tr("Undo"));
	undoAction->setShortcut(QKeySequence::Undo);
	undoAction->setIcon(QIcon(":/icons/undo.png"));
	connect(undoAction,SIGNAL(triggered()),this,SLOT(undo()));
	
	QAction *redoAction = new QAction(editionMenu);
	redoAction->setText(tr("Redo"));
	redoAction->setShortcut(QKeySequence::Redo);
	redoAction->setIcon(QIcon(":/icons/redo.png"));
	connect(redoAction,SIGNAL(triggered()),this,SLOT(redo()));
	
	QAction *cutAction = new QAction(editionMenu);
	cutAction->setText(tr("Cut"));
	cutAction->setShortcut(QKeySequence::Cut);
	cutAction->setIcon(QIcon(":/icons/cut.png"));
	connect(cutAction,SIGNAL(triggered()),this,SLOT(cut()));
	
	QAction *copyAction = new QAction(editionMenu);
	copyAction->setText(tr("Copy"));
	copyAction->setShortcut(QKeySequence::Copy);
	copyAction->setIcon(QIcon(":/icons/copy.png"));
	connect(copyAction,SIGNAL(triggered()),this,SLOT(copy()));
	
	QAction *pasteAction = new QAction(editionMenu);
	pasteAction->setText(tr("Paste"));
	pasteAction->setShortcut(QKeySequence("Ctrl+V"));
	pasteAction->setIcon(QIcon(":/icons/paste.png"));
	connect(pasteAction,SIGNAL(triggered()),this,SLOT(paste()));
	
	QAction *selectAllAction = new QAction(editionMenu);
	selectAllAction->setText(tr("Select all"));
	selectAllAction->setShortcut(QKeySequence::SelectAll);
	selectAllAction->setIcon(QIcon(":/icons/select_all.png"));
	connect(selectAllAction,SIGNAL(triggered()),this,SLOT(selectAll()));
	
	QAction *goToLineAction = new QAction(parent);
	goToLineAction->setText(tr("Go to line"));
	goToLineAction->setIcon(QIcon(":/icons/goto_line.png"));
	goToLineAction->setShortcut(QKeySequence("Ctrl+G"));
	connect(goToLineAction,SIGNAL(triggered()),this,SLOT(showGoToLineWidget()));
	
	QAction *findAction = new QAction(parent);
	findAction->setText(tr("Find or Replace"));
	findAction->setIcon(QIcon(":/icons/find.png"));
	findAction->setShortcuts(QList<QKeySequence>() << QKeySequence("Ctrl+F") << QKeySequence("Ctrl+R"));
	connect(findAction,SIGNAL(triggered()),this,SLOT(showFindReplaceWidget()));
	
	editionMenu->addAction(undoAction);
	editionMenu->addAction(redoAction);
	editionMenu->addSeparator();
	editionMenu->addAction(selectAllAction);
	editionMenu->addAction(cutAction);
	editionMenu->addAction(copyAction);
	editionMenu->addAction(pasteAction);
	editionMenu->addSeparator();
	editionMenu->addAction(goToLineAction);
	editionMenu->addAction(findAction);
	
	toolBar->addAction(undoAction);
	toolBar->addAction(redoAction);
	toolBar->addAction(cutAction);
	toolBar->addAction(copyAction);
	toolBar->addAction(pasteAction);
	toolBar->addSeparator();
	toolBar->addAction(goToLineAction);
	toolBar->addAction(findAction);
	toolBar->setOrientation(Qt::Vertical);
	toolBar->setIconSize(QSize(16,16));
	
	parent->addAction(goToLineAction);
	parent->addAction(findAction);
	
	editionActions << undoAction << redoAction << selectAllAction << cutAction << copyAction 
					<< pasteAction;
	
	QAction *settingsAction = new QAction(parent);
	settingsAction->setText(tr("Settings"));
	settingsAction->setIcon(QIcon(":/icons/settings.png"));
	settingsAction->setShortcut(QKeySequence("F10"));
	connect(settingsAction,SIGNAL(triggered()),this,SLOT(showSettings()));
	
	QAction *sessionsAction = new QAction(parent);
	sessionsAction->setText(tr("Sessions manager"));
	sessionsAction->setIcon(QIcon(":/icons/sessions_manager.png"));
	sessionsAction->setShortcut(QKeySequence("F9"));
	connect(sessionsAction,SIGNAL(triggered()),sessionsManager,SLOT(exec()));
	
	toolsMenu->addAction(settingsAction);
	toolsMenu->addAction(sessionsAction);
	
	parent->addAction(settingsAction);
	parent->addAction(sessionsAction);
	
	toolsActions << settingsAction << sessionsAction;
	
	QAction *aboutEditorAction = new QAction(parent);
	aboutEditorAction->setText(tr("About Vialinx Editor"));
	aboutEditorAction->setIcon(QIcon(":/icons/main.png"));
	connect(aboutEditorAction,SIGNAL(triggered()),aboutEditorDialog,SLOT(exec()));
	
	QAction *informationAction = new QAction(parent);
	informationAction->setText(tr("Information"));
	informationAction->setIcon(QIcon(":/icons/about.png"));
	connect(informationAction,SIGNAL(triggered()),informationDialog,SLOT(exec()));
	
	helpActions << informationAction << aboutEditorAction;
	
	// Add actions to context menu
	contextMenu->addAction(undoAction);
	contextMenu->addAction(redoAction);
	contextMenu->addSeparator();
	contextMenu->addAction(selectAllAction);
	contextMenu->addAction(cutAction);
	contextMenu->addAction(copyAction);
	contextMenu->addAction(pasteAction);
	
	// Create invisible actions
	QAction *unindentLinesAction = new QAction(this);
	unindentLinesAction->setShortcut(QKeySequence("Shift+Tab"));
	connect(unindentLinesAction,SIGNAL(triggered()),this,SLOT(unindentSelectedLines()));
	
	QAction *commentLinesAction = new QAction(this);
	commentLinesAction->setShortcut(QKeySequence("Ctrl+D"));
	connect(commentLinesAction,SIGNAL(triggered()),this,SLOT(commentSelectedText()));
	
	QAction *previousEditorAction = new QAction(this);
	previousEditorAction->setShortcut(QKeySequence("Alt+Left"));
	connect(previousEditorAction,SIGNAL(triggered()),this,SLOT(previousEditor()));
	
	QAction *nextEditorAction = new QAction(this);
	nextEditorAction->setShortcut(QKeySequence("Alt+Right"));
	connect(nextEditorAction,SIGNAL(triggered()),this,SLOT(nextEditor()));
	
	invisibleActions << unindentLinesAction << commentLinesAction << previousEditorAction << nextEditorAction;
	
	changeLinesEndFormatComboBox = new QComboBox;
	changeLinesEndFormatComboBox->addItem(QIcon(":/icons/tux.png"),"Linux");
	changeLinesEndFormatComboBox->addItem(QIcon(":/icons/win.png"),"Windows");
	changeLinesEndFormatComboBox->addItem(QIcon(":/icons/mac.png"),"Mac OS");
	
	QSettings settings(ORGANIZATION,PROGRAM_NAME);
	int mode = settings.value("Interface/EolMode",-1).toInt();
	if (mode == -1) {
#ifdef Q_OS_WIN
		mode = 1;
#endif
#ifdef Q_OS_UNIX
		mode = 0;
#endif
#ifdef Q_OS_MAC
		mode = 2;
#endif
	}
	changeLinesEndFormatComboBox->setCurrentIndex(mode);
	changeLinesEndFormatComboBox->setToolTip(tr("Choose end of line mode"));
	
	connect(changeLinesEndFormatComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(changeEolMode(int)));
	
	changeSyntaxComboBox = new QComboBox;
	changeSyntaxComboBox->addItem(tr("Without Syntax"));
	changeSyntaxComboBox->addItem("C++",QStringList() << "cpp" << "h" << "cxx" << "c++");
	changeSyntaxComboBox->addItem("Bash",QStringList() << "bash" << "run" << "sh");
	changeSyntaxComboBox->addItem("CSS",QStringList() << "css");
	changeSyntaxComboBox->addItem("C#",QStringList() << "cs");
	changeSyntaxComboBox->addItem("Diff",QStringList() << "patch");
	changeSyntaxComboBox->addItem("D",QStringList() << "d");
	changeSyntaxComboBox->addItem("HTML",QStringList() << "html" << "htm" << "php");
	changeSyntaxComboBox->addItem("JavaScript",QStringList() << "js");
	changeSyntaxComboBox->addItem("Perl",QStringList() << "pl" << "pm" << "cgi");
	changeSyntaxComboBox->addItem("Python",QStringList() << "py");
	changeSyntaxComboBox->addItem("SQL",QStringList() << "sql");
	
	connect(changeSyntaxComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(changeSyntax(int)));
	
	changeEncodingComboBox = new QComboBox;
	changeEncodingComboBox->addItems(QStringList() 
	<< tr("System encoding") << "Apple Roman" << "Big5" << "Big5-HKSCS" << "EUC-JP" << "EUC-KR" << "GB18030-0"
	<< "IBM 850" << "IBM 866" << "IBM 874" << "ISO 2022-JP" << "ISO 8859-1" << "ISO 8859-10" << "ISO 8859-13"
	<< "ISO 8859-14" << "ISO 8859-15" << "ISO 8859-16" << "ISO 8859-2" << "ISO 8859-3" << "ISO 8859-4"
	<< "ISO 8859-5" << "ISO 8859-6" << "ISO 8859-7" << "ISO 8859-8" << "ISO 8859-9" << "Iscii-Bng" << "Iscii-Dev"
	<< "Iscii-Gjr" << "Iscii-Knd" << "Iscii-Mlm" << "Iscii-Ori" << "Iscii-Pnj" << "Iscii-Tlg" << "Iscii-Tml"
	<< "JIS X 0201" << "JIS X 0208" << "KOI8-R" << "KOI8-U" << "MuleLao-1" << "ROMAN8" << "Shift-JIS"
	<< "TIS-620" << "TSCII" << "UTF-16" << "UTF-16BE" << "UTF-16LE" << "UTF-8" << "WINSAMI2" << "Windows-1250"
	<< "Windows-1251" << "Windows-1252" << "Windows-1253" << "Windows-1254" << "Windows-1255" << "Windows-1256"
	<< "Windows-1257" << "Windows-1258");
		
	connect(changeEncodingComboBox,SIGNAL(currentIndexChanged(const QString&)),this,SLOT(setEncoding(const QString&)));
		
	widgetsForStatusBar << changeSyntaxComboBox << changeEncodingComboBox << changeLinesEndFormatComboBox;
		
	connect(this,SIGNAL(contextMenuCalled(int,int)),this,SLOT(showContextMenu(int,int)));
	connect(this,SIGNAL(currentEditorChanged(Editor *)),this,SLOT(currentEditorChanged(Editor *)));
	connect(this,SIGNAL(currentTabTextChanged(const QString&)),this,SLOT(emitSignalToChangeWindowTitle(const QString&)));
	connect(sessionsManager,SIGNAL(currentSessionChanged(const QString&)),
		 this,SLOT(emitSignalToChangeWindowTitleBecauseOfSession(const QString&)));
}

Interface::~Interface() {
	saveSettings();
	sessionsManager->saveSettings();
	
	delete fileMenu;
	delete editionMenu;
	delete toolsMenu;
	delete contextMenu;
	delete toolBar;
	delete changeSyntaxComboBox;
	delete changeEncodingComboBox;
	delete changeLinesEndFormatComboBox;
	delete sessionsManager;
	delete aboutEditorDialog;
	delete informationDialog;
}

QMenu *Interface::getFilesManagementMenu() const {
	return fileMenu;
}

QMenu *Interface::getEditionMenu() const {
	return editionMenu;
}

QMenu *Interface::getToolsMenu() const {
	return toolsMenu;
}

QToolBar *Interface::getToolBar() const {
	return toolBar;
}

const ActionsList& Interface::getFilesManagementActions() const {
	return filesManagementActions;
}

const ActionsList& Interface::getEditionActions() const {
	return editionActions;
}

const ActionsList& Interface::getToolsActions() const {
	return toolsActions;
}

const ActionsList& Interface::getInvisibleActions() const {
	return invisibleActions;
}

const WidgetsList& Interface::getWidgetsForStatusBar() const {
	return widgetsForStatusBar;
}

const ActionsList& Interface::getHelpActions() const {
	return helpActions;
}

void Interface::showContextMenu(int globalX,int globalY) {
	contextMenu->move(globalX,globalY);
	contextMenu->exec();
}

void Interface::currentEditorChanged(Editor *editor) {
	if (editor == 0) {
		changeEncodingComboBox->setCurrentIndex(0);
		changeSyntaxComboBox->setCurrentIndex(0);
		return;
	}
	
	FileInfo *fileInfo = getFileInfoOfEditor(editor);
	changeSyntaxComboBox->blockSignals(true);
	changeEncodingComboBox->blockSignals(true);
	if (fileInfo != 0) {
		changeEncodingComboBox->setCurrentIndex(0);
		changeSyntaxComboBox->setCurrentIndex(0);
		for (int i = 0; i < changeEncodingComboBox->count(); i++)
			if (fileInfo->fileEncoding == changeEncodingComboBox->itemText(i)) {
				changeEncodingComboBox->setCurrentIndex(i);
				break;
			}
		for (int i = 0; i < changeSyntaxComboBox->count(); i++)
			if (changeSyntaxComboBox->itemData(i).toStringList().contains(fileInfo->extenssionForSyntax)) {
				changeSyntaxComboBox->setCurrentIndex(i);
				break;
			}
	}
	changeSyntaxComboBox->blockSignals(false);
	changeEncodingComboBox->blockSignals(false);
}

void Interface::changeSyntax(int syntaxIndex) {
	QStringList extenssions = changeSyntaxComboBox->itemData(syntaxIndex).toStringList();
	if (extenssions.isEmpty())
		setSyntaxForExtenssion(QString());
	else
		setSyntaxForExtenssion(extenssions.first());
}

void Interface::loadPlugins() {
	
}

void Interface::emitSignalToChangeWindowTitle(const QString& currentFileName) {
	if (sessionsManager->getCurrentSessionName().isEmpty()) {
		emit (changeWindowTitle(currentFileName));
		return;
	}
	emit(changeWindowTitle(currentFileName + " - " + sessionsManager->getCurrentSessionName()));
}

void Interface::emitSignalToChangeWindowTitleBecauseOfSession(const QString&) {
	emitSignalToChangeWindowTitle(getCurrentTabText());
}

void Interface::saveSettings() {
	QSettings settings(ORGANIZATION,PROGRAM_NAME);
	settings.setValue("Interface/EolMode",changeLinesEndFormatComboBox->currentIndex());
}
